package com.heima.comment.service.impl;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.heima.aliyunsecurity.GreenTextScan;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustomException;
import com.heima.feigns.user.UserFeign;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.utils.threadlocal.AppThreadLocalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author admin
 */
@Service
public class CommentServiceImpl implements CommentService {

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private UserFeign userFeign;

    @Resource
    private GreenTextScan greenTextScan;

    @Resource
    private CommentHotService commentHotService;

    /**
     * @param dto app评论请求携带数据封装对象
     * @return 保存结果
     * @Description 保存评论
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //1. 校验参数
        if (ObjectUtils.isEmpty(dto.getArticleId())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if (!ObjectUtils.isEmpty(dto.getContent()) && dto.getContent().length() > 140) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "评论内容不能超过140字");
        }
        //2. 判断是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (ObjectUtils.isEmpty(user)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3. 查询完整用户信息
        ApUser apUser = userFeign.findUserById(user.getId().longValue());
        if (ObjectUtils.isEmpty(apUser)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "用户数据出错！");
        }
        //4. 检验文本安全
        Map map = null;
        try {
            map = greenTextScan.greenTextScan(dto.getContent());
        } catch (Exception e) {
            e.printStackTrace();
        }
        String suggestion = (String) map.get("suggestion");
        if ("pass".equals(suggestion)) {
            ApComment apComment = new ApComment();
            apComment.setAuthorId(apUser.getId());
            apComment.setAuthorName(apUser.getName());
            apComment.setImage(apUser.getImage());
            apComment.setContent(dto.getContent());
            apComment.setEntryId(dto.getArticleId());
            apComment.setCreatedTime(new Date());
            apComment.setUpdatedTime(new Date());
            apComment.setLikes(0);
            apComment.setReply(0);
            apComment.setType((short) 0);
            apComment.setFlag((short) 0);
            mongoTemplate.insert(apComment);
            return ResponseResult.okResult();
        } else {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_ERROR, "评论内容违规");
        }
    }

    /**
     * @param dto app评论点赞请求携带数据封装对象
     * @return 保存结果
     * @Description 点赞某一条评论
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //1 参数检查
        if (ObjectUtils.isEmpty(dto) || ObjectUtils.isEmpty(dto.getCommentId())) {
            CustomException.custom(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if (dto.getOperation() != 0 && dto.getOperation() != 1) {
            CustomException.custom(AppHttpCodeEnum.PARAM_INVALID, "点赞方式参数错误");
        }
        //2 判断用户登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (ObjectUtils.isEmpty(user)) {
            CustomException.custom(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3 查询评论
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (ObjectUtils.isEmpty(apComment)) {
            CustomException.custom(AppHttpCodeEnum.DATA_NOT_EXIST, "该回复信息不存在");
        }
        // 用户不能重复点赞
        Query query = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").is(dto.getCommentId()));
        ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
        if (!ObjectUtils.isEmpty(apCommentLike) && apCommentLike.getOperation() == 0 && dto.getOperation() == 0) {
            CustomException.custom(AppHttpCodeEnum.DATA_EXIST, "不能重复点赞");
        }
        //4. 保存点赞数据
        if (dto.getOperation() == 0) {
            // 点赞数+1 保存评论信息
            apComment.setLikes(apComment.getLikes() + 1);
            mongoTemplate.save(apComment);
            if (apComment.getLikes() >= 5 && apComment.getFlag() == 0) {
                commentHotService.hotCommentExecutor(apComment.getEntryId(), apComment);
            }
            // 保存点赞信息
            apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(user.getId());
            apCommentLike.setCommentId(apComment.getId());
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.save(apCommentLike);
        } else {
            // 取消点赞
            apComment.setLikes(
                    apComment.getLikes() <= 0 ? 0 : apComment.getLikes() - 1);
            mongoTemplate.save(apComment);

            //删除点赞评论信息
            mongoTemplate.remove(query, ApCommentLike.class);
        }
        //5 返回数据
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("likes", apComment.getLikes());
        return ResponseResult.okResult(resultMap);
    }

    /**
     * @param dto 回复列表请求数据封装对象
     * @return 查询结果
     * @Description 查询评论回复
     */
    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        //1 校验参数
        if (ObjectUtils.isEmpty(dto) || ObjectUtils.isEmpty(dto.getArticleId())) {
            CustomException.custom(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Integer size = dto.getSize();
        if (ObjectUtils.isEmpty(size) || size <= 0) {
            dto.setSize(10);
        }
        //2 Mongo查询文章中所有评论
        List<ApComment> apCommentList = mongoTemplate.find(
                Query.query(Criteria.where("entryId").is(dto.getArticleId())
                        .and("createdTime").lt(dto.getMinDate()))
                        .limit(dto.getSize())
                        .with(Sort.by(Sort.Direction.DESC, "createdTime")),
                ApComment.class);
        //3 封装查询结果
        //3.1 若用户未登录直接返回评论列表
        ApUser user = AppThreadLocalUtils.getUser();
        if (ObjectUtils.isEmpty(user)) {
            return ResponseResult.okResult(apCommentList);
        }
        //3.2 用户已登录，查看当前用户对评论的点赞情况
        List<ApCommentVo> apCommentVoList = new ArrayList<>();
        // 获取文章对应的所有评论ID列表
        List<String> idList = apCommentList.stream().map(ApComment::getId).collect(Collectors.toList());
        // 查询 点赞批量列表 按照评论id 筛选
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(
                Query.query(Criteria.where("commentId").in(idList)
                        .and("authorId").is(user.getId()))
                , ApCommentLike.class);
        // 遍历当前用户点赞列表 和当前评论列表
        if (apCommentList.size() > 0 && apCommentLikes.size() > 0) {
            apCommentList.forEach(comment -> {
                //遍历所有文章列表ID
                ApCommentVo apCommentVo = new ApCommentVo();
                BeanUtils.copyProperties(comment, apCommentVo);
                //遍历当前用户点赞列表
                apCommentLikes.forEach(apCommentLike -> {
                    // 文章评论列表id 和 当前用户点赞评论列表id是否相等
                    if (comment.getId().equals(apCommentLike.getCommentId())) {
                        apCommentVo.setOperation((short) 0);
                    }
                });
                apCommentVoList.add(apCommentVo);
            });
            return ResponseResult.okResult(apCommentVoList);
        }
        return ResponseResult.okResult(apCommentList);
    }

}